﻿
using System;
using System.Collections.Generic; 
using UnityEngine;
using XFABManager; 

namespace XFGameFramework.TweenSystem
{
    /// <summary>
    /// 渐变对象
    /// </summary>
    public class Tweener : CustomAsyncOperation<Tweener>
    {

       

        #region 字段
        private bool _isPlaying = false;
        [Tooltip("动画已经执行的时间")]
        private float timer = 0;
        private bool inDelay = true;
        private bool isFirstFrame = true;
        private bool moveTarget = true;
        [Tooltip("动画的持续时间")]
        private float duration;

        [Tooltip("进度增量")]
        private float progressDetal;

        private GameObject gameObject;

        private bool bindingWithGameObject;

        private int loopCount = -1; // -1代表一直循环

        private Component targetComponent;
         
        #endregion
         
        #region 属性 

        /// <summary>
        /// 持续时间
        /// </summary>
        public float Duration 
        {
            get { 
                return duration;
            }
            internal set { 
                duration = value;
            }
        }

        /// <summary>
        /// 循环模式
        /// </summary>
        public LoopMode LoopMode { get; internal set; }

        /// <summary>
        /// 缓动曲线
        /// </summary>
        public Ease Ease { get; internal set; }

        /// <summary>
        /// 是否忽略时间缩放
        /// </summary>
        public bool IgnoreTimeScale { get; internal set; }

        /// <summary>
        /// 自定义的缓动曲线
        /// </summary>
        public AnimationCurve Curve { get; internal set; }

        /// <summary>
        /// 延迟
        /// </summary>
        public float Delay { get; internal set; }

        /// <summary>
        /// 是否在运行中
        /// </summary>
        public bool isPlaying
        {
            get
            {
                return _isPlaying;
            }
            protected set
            {
                _isPlaying = value;
            } 
        }

        internal bool isRuning { get; set; } = false;


        public Component Component
        {
            get {
                return targetComponent;
            }
            set 
            {
                targetComponent = value;
                BindingWithComponent = value;
            }
        }
       
        /// <summary>
        /// 动画已经执行的时间
        /// </summary>
        public float Timer => timer;

        /// <summary>
        /// 进度增量
        /// </summary>
        public float ProgressDetal => progressDetal;

        /// <summary>
        /// 绑定的游戏物体
        /// </summary>
        public GameObject GameObject 
        {
            get 
            { 
                return gameObject;
            }
            internal set 
            { 
                gameObject = value;
                bindingWithGameObject = gameObject;

                if (gameObject)
                {
                    if (Listener != null) 
                    { 
                        Listener.onDisable.RemoveListener(OnDisable);
                        Listener.onDisable.AddListener(OnDisable); 
                    }

                    GameObjectHashCode = gameObject.GetHashCode();
                }

            }
        }

        /// <summary>
        /// 是否绑定游戏物体
        /// </summary>
        public bool BindingWithGameObject => bindingWithGameObject;

        private bool BindingWithComponent { get; set; } = false;

        internal int GameObjectHashCode { get; set; }

        /// <summary>
        /// 循环的次数
        /// </summary>
        public int LoopCount
        {
            get 
            { 
                return loopCount;
            }
            set 
            { 
                loopCount = value;
            }
        }

        public MonoEventListener Listener
        {
            get 
            {

                if (BindingWithGameObject && GameObject) 
                {
                    MonoEventListener listener = gameObject.GetComponent<MonoEventListener>();
                    if (listener == null)
                        listener = gameObject.AddComponent<MonoEventListener>();

                    return listener;
                }

                return null;
            }
        }

        #endregion


        #region  事件 

        /// <summary>
        /// 动画执行中触发!
        /// </summary>
        public Action<Tweener> onTween;

        /// <summary>
        /// 中断动画时触发
        /// </summary>
        public Action<Tweener> onKill;

        #endregion

         
        #region 方法


        /// <summary>
        /// 开始播放动画
        /// </summary>
        internal void Play(float progress = 0)
        {
            // 如果动画已经运行,直接return , 不能重复运行
            if (isRuning) return; 
            isRuning = true;

            this.progress = progress;
            isCompleted = false;
            isPlaying = true;

            TweenManager.AddTweener(this);
            
            moveTarget = true;
            inDelay = true;
            timer = Duration * progress;
            isFirstFrame = progress == 0;
            Update();
        }
         
        /// <summary>
        /// 停止播放该动画
        /// </summary>
        public void Kill()
        {
            if (isDone) return;
            //   因为这个异步操作没有完成，而是被中断了, 所以不应该触发完成的事件 
            CompletedWithoutNotify();
            // 触发中断的事件
            TriggerOnKill();

            // 移除 Tweener
            TweenManager.RemoveTweener(this);
        }
         
        /// <summary>
        /// 暂停或取消暂停
        /// </summary>
        /// <param name="pause"></param>
        public void Pause(bool pause)
        {
            isPlaying = !pause;
        }
         
        internal void Update()
        { 
            if (BindingWithComponent)
            {
                if (!Component)
                {
                    // 已绑定的组件 如果组件为空 直接中断
                    Kill();
                    return;
                }
            }

            // 如果这个动画 绑定的游戏物体被隐藏或销毁 直接中断
            if (BindingWithGameObject)
            {
                if (!GameObject || !GameObject.activeInHierarchy)
                {
                    // 已绑定游戏物体 并且 该游戏物体被销毁或被隐藏
                    Kill();
                    return;
                }
            }

            // 暂停的话直接return
            if (!isPlaying) 
            { 
                return;
            }
             
            if (Delay > 0 && inDelay)
            {
                timer += TimeExtensions.GetDeltaTime(IgnoreTimeScale);

                if (timer >= Delay)
                {
                    timer = 0;
                    inDelay = false;
                }

                return;
            }

            if (Duration <= 0)
            {
                progress = 1;
                TriggerOnTwwen();
                Completed();
                return;
            }

            if (isFirstFrame)
            {
                progress = 0;
                TriggerOnTwwen();
                isFirstFrame = false;
                return;
            }

            switch (LoopMode)
            {
                case LoopMode.Once:
                    UpdateOnce();
                    break;
                case LoopMode.Loop:
                    UpdateLoop();
                    break;
                case LoopMode.Pingpong:
                    UpdatePingpong();
                    break;
            }
        }

        private void UpdateOnce()
        {  
            timer += TimeExtensions.GetDeltaTime(IgnoreTimeScale);

            if (timer >= Duration)
            {
                timer = Duration;
                UpdateProgress();
                Completed(); 
            }
            else
            {
                UpdateProgress(); 
            } 
        }

        private void UpdateLoop()
        { 
            if (timer >= Duration)
            {
                //循环 从头开始
                timer = 0; 
                UpdateProgress();
                return;
            }

            timer += TimeExtensions.GetDeltaTime(IgnoreTimeScale);

            if (timer >= Duration)
            {
                timer = Duration;

                if (LoopCount > 0)
                {
                    LoopCount--;
                    if (LoopCount <= 0) 
                    {
                        // 循环结束
                        UpdateProgress();
                        Completed();
                        return;
                    }
                }

            }

            UpdateProgress();
        }
         
        private void UpdatePingpong()
        {
            if (moveTarget)
                timer += TimeExtensions.GetDeltaTime(IgnoreTimeScale);
            else
                timer -= TimeExtensions.GetDeltaTime(IgnoreTimeScale);
             
            if (moveTarget && timer >= Duration)
            {
                timer = Duration;
                moveTarget = false;
            }
            else if (!moveTarget && timer <= 0)
            {
                timer = 0; 
                moveTarget = true;

                if (LoopCount > 0)
                {
                    LoopCount--;
                    if (LoopCount <= 0) 
                    {
                        // 循环结束
                        UpdateProgress();
                        Completed();
                        return;
                    }
                } 
            }
              
            UpdateProgress();
        }
         
        private float GetProgress(float x)
        {
            if (Ease == Ease.Custom)
            {
                if (Curve != null)
                    return Curve.Evaluate(x);
            }
            else
                return EaseManager.Evaluate(Ease, x);

            return x;
        }

        private void UpdateProgress() 
        {
            float p = GetProgress(timer / Duration);
            progressDetal = p - progress; 
            progress = p;
            TriggerOnTwwen();
        }


        protected override void OnCompleted()
        {
            base.OnCompleted();
            // 动画结束 isPlaying 设置为false
            isPlaying = false;

            isRuning = false; // 动画结束 停止运行
            //TweenManager.RemoveTweener(this);
        }


        private void TriggerOnTwwen() 
        {
            try
            {
                onTween?.Invoke(this);
            }
            catch (Exception e)
            { 
                Debug.LogException(e);
            }
            
        }


        private void TriggerOnKill() 
        {
            try
            {
                onKill?.Invoke(this);
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            } 
        }


        private void OnDisable() 
        { 
            Kill();
            if (Listener != null) 
                Listener.onDisable.RemoveListener(OnDisable);
            
        }

        #endregion

    }

}